<?php
require_once 'UE/Cache/Abstract.php';

/**
 * 文件缓存
 * 
 * ============================================================================
 * 版权所有: (c) 2009-2011，<UEShop Inc>，并保留所有权利。
 * 网站地址: http://www.ueshop.cn
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * @author cmpan
 * @copyright   Copyright (c) 2009-2011 UEShop Inc. (http://www.ueshop.cn)
 * @license     http://www.ueshop.cn/1_0.txt
 */
class UE_Cache_File extends UE_Cache_Abstract {
	
	protected $_cachesDir = 'data/cache';
	
	public function hashKey($key) {
		$key = md5($key);
		if(strlen($key) < 2) {
			$key = $key . '_';
		}
		
		return 	"{$key[0]}{$key[1]}/{$key}";
	}
		
	public function __construct() {
		if (defined('CACHE_DIR')) {
			$this->_setCacheDir(CACHE_DIR);
		}
	}
	
	/**
	 * 获取缓存文件
	 *
	 * @param string $key
	 * @return string
	 */
	protected function _getCacheFile($key) {
		return $this->_cachesDir . '/' . ltrim($key, '/') . '.php';
	}

    /**
	 * 读取缓存变量
	 * 为防止信息泄露，缓存文件格式为php文件
	 * 
	 * @param string $key 缓存下标
	 * @return mixed
	 */
    public function fetch($key) {
        $cacheFile = self::_getCacheFile($key);
        if (is_file($cacheFile) && is_readable($cacheFile)) {
            //return unserialize(@file_get_contents($cacheFile, false, NULL, 13));
			return include $cacheFile;
        }

        return false;
    }

	/**
	 * 缓存变量
	 * 为防止信息泄露，缓存文件格式为php文件，并以"<?php exit;?>"开头
	 *
	 * @param string $key 缓存变量下标
	 * @param string $value 缓存变量的值
	 * @return bool
	 */
    public function store($key, $value) {
		$cacheFile = self::_getCacheFile($key);
		$cacheDir  = dirname($cacheFile);

		if(!is_dir($cacheDir)) {
		    if(!@mkdir($cacheDir, 0755, true)) {
			    throw new UE_Cache_Exception("Could not make cache directory");
		    }
		}
		/*
		if(false !== strpos($key, '/')) {
			$key = substr($key, strrpos($key, '/') + 1);
		}
		*/
        return @file_put_contents($cacheFile, "<?php \r\n// UE cache file, please don't edit me!\r\n"
			                                . "// Created: " . date('Y-m-d H:i:s') . " (" . microtime(1) . ")\r\n"
			                                . "// Cache: {$cacheFile}\r\n"
		                                    . "\r\ndefined('UE_IN') || die('Access Denied');\r\n\r\nreturn " . var_export($value, true) . ';');
	}

	/**
	 * 删除缓存变量
	 *
	 * @param string $key 缓存下标
	 * @return Cache_File
	 */
    public function delete($key) {
    	if(empty($key)) {
		    throw new UE_Cache_Exception("Missing argument 1 for UE_Cache_File::delete()");
		}
		
		$file = self::_getCacheFile($key);
		is_file($file) && @unlink($file);

		return $this;
	}

	/**
	 * 缓存单元是否已经锁定
	 *
	 * @param string $key
	 * @return bool
	 */
	public function isLocked($key) {
		$cacheFile = self::_getCacheFile($key);
		clearstatcache();
		return is_file($cacheFile . '.lock');
	}

	/**
	 * 锁定
	 *
	 * @param string $key
	 * @return UE_Cache_File
	 */
	public function lock($key) {
		$cacheFile = self::_getCacheFile($key);
		$cacheDir  = dirname($cacheFile);
		if(!is_dir($cacheDir)) {
		    if(!@mkdir($cacheDir, 0755, true)) {
			    if(!is_dir($cacheDir)) {
			        throw new UE_Cache_Exception("Could not make cache directory");
			    }
		    }
		}

		// 设定缓存锁文件的访问和修改时间
		@touch($cacheFile . '.lock');
		return $this;
	}
  
	/**
	 * 解锁
	 *
	 * @param string $key
	 * @return UE_Cache_File
	 */
	public function unlock($key) {
		$cacheFile = self::_getCacheFile($key);
	    @unlink($cacheFile . '.lock');
		return $this;
	}

	/**
	 * 设置文件缓存目录
	 * @param string $dir
	 * @return UE_Cache_File
	 */
	protected function _setCacheDir($dir) {
		$this->_cachesDir = rtrim(str_replace('\\', '/', trim($dir)), '/');
		clearstatcache();
		if(!is_dir($this->_cachesDir)) {
			mkdir($this->_cachesDir, 0755, true);
		}
		//
		return $this;
	}
			
	/**
	 * 清空所有缓存
	 *
	 * @return UE_Cache_File
	 */
	public function clear($dir = '') {
		$dir = rtrim($this->_cachesDir, '/') . '/'.$dir;
		clearDir($dir);
		
		return $this;
	}	
}
